/**
 * 下钻
 * demo
 *
 *
 *
 *
import DrillDown from "../../MapCommon/DrillDown";
 let drillDown=new DrillDown(map);
 drillDown.setCallBack(res=>{
              console.log("下钻",res)
            })
 drillDown.iniLayer(["地市域","县域"],true)
 *
 */
import turf from "turf"
import turf_line_intersect from "@turf/line-intersect"

export default class MapCommon {
  /**
   * 根据条件过滤指定图层，给地图增加过滤条件
   * @param map 地图对象
   * @param filterProp 过滤字段
   * @param filter 过滤条件
   * @param layer 过滤图层
   * @param commonSrcLayers 其他同源图层
   * @returns {[string]} 最新过滤条件
   */
  static filterLayers(map,filterProp,filter,layer,commonSrcLayers){
    if(!map.getLayer(layer)){
      // console.log(layer+' 图层不存在!')
      return
    }
    if(!filter || filter.length===0 || !layer || !map.getLayer(layer)){return}
    //修改选中图层filter
    //单个filter及多个filter均使用all模式
    let newFilter=["all"];
    let initFilter=[]
    //case1:图层无filter
    if(!(map.getLayer(layer)).filter){
      newFilter.push(filter.slice(0,3));
    }
    else{//case2:兼容既有filter
      //存储图层原始filter
      if(initFilter.length===0){
        initFilter=map.getLayer(layer).filter;
      }
      let temp=JSON.parse(JSON.stringify(initFilter));
      //case2-1:原有filter为组合filter
      if(temp[0]==='all' || temp[0]==='or'){
        //检测是否已有该字段过滤条件
        let index=-1
        let flag=false
        for(let i=0;i<temp.length;i++){
          if(temp[i] instanceof Array && temp[i][1]===filterProp){
            index=i;
            flag=true;
            break;
          }
        }
        if(flag && index!==-1){
          temp[index]=filter
        }
        if(flag===false){
          temp.push(filter);//加入新的filter
        }

        newFilter=temp;
      }else{//case2-2:非组合
        newFilter.push(temp.slice(0,3));
        newFilter.push(filter);
      }
    }
    map.setLayoutProperty(layer, "visibility", "visible");
    map.setFilter(layer,newFilter);
    if(commonSrcLayers && commonSrcLayers.length>0){
      for(let i=0,l=commonSrcLayers.length;i<l;i++){
        if(map.getLayer(commonSrcLayers[i])){
          map.setLayoutProperty(commonSrcLayers[i], "visibility", "visible");
          map.setFilter(commonSrcLayers[i],newFilter);
        }
      }
    }
    return newFilter
  }


  /**
   * 关闭图层所有点击事件
   * @param map 地图对象
   * @param srcLayerName 原图层名字
   */
  static offClickLayer(map,srcLayerName) {
    if(!map){
      throw new Error("地图对象不能为空")
    }
    let srcLayer=map.getLayer(srcLayerName)
    if(!srcLayer){
      throw new Error(srcLayerName+"原图层不存在")
    }
    map.off('click',srcLayerName)
  }

  /**
   * 将原图层复制为一个可点击的面图层
   * @param map 地图对象
   * @param srcLayerName 原图层名字
   * @param targetLayerName 点击图层名字
   * @param clickCallBack 点击回调
   * @param context 上下文
   */
  static addClickLayer(map,srcLayerName,targetLayerName,clickCallBack,context) {
    if(!map){
      throw new Error("地图对象不能为空")
    }
    let srcLayer=map.getLayer(srcLayerName)
    if(!srcLayer){
      throw new Error(srcLayerName+"原图层不存在")
    }
    if(map.getLayer(targetLayerName)){
      throw new Error(targetLayerName+"图层已存在")
    }
    map.addLayer({
      id:targetLayerName,
      type:"fill",
      "source": srcLayer.source,
      "source-layer": srcLayer.sourceLayer,
      "minzoom": srcLayer.minzoom,
      "maxzoom": srcLayer.maxzoom,
      layout: {
        visibility:"visible"
      },
      paint: {
        "fill-opacity": 0,
      },
    })
    if(clickCallBack){
      map.on('click',targetLayerName,e=>{
        clickCallBack(e,context)
      })
    }
  }
  /**
   * 将原图层复制为一个可点的面图层
   * @param map 地图对象
   * @param srcLayerName 原图层名字
   * @param targetLayerName 点击图层名字
   * @param clickCallBack 点击回调
   * @param context 上下文
   */
  static copyLineToArea(map,srcLayerName,targetLayerName) {
    if(!map){
      throw new Error("地图对象不能为空")
    }
    let srcLayer=map.getLayer(srcLayerName)
    if(!srcLayer){
      throw new Error(srcLayerName+"原图层不存在")
    }
    if(map.getLayer(targetLayerName)){
      throw new Error(targetLayerName+"图层已存在")
    }
    map.addLayer({
      id:targetLayerName,
      type:"fill",
      "source": srcLayer.source,
      "source-layer": srcLayer.sourceLayer||"",
      "minzoom": srcLayer.minzoom,
      "maxzoom": srcLayer.maxzoom,
      layout: {
        visibility:"visible"
      },
      paint: {
        "fill-opacity": 0,
      },
    })
  }
  /**
   * 将原图层复制为一个可点的面图层
   * @param map 地图对象
   * @param srcLayerName 原图层名字
   * @param targetLayerName 点击图层名字
   * @param clickCallBack 点击回调
   * @param context 上下文
   */
  static copyLineToAreaFit(map,srcLayerName,targetLayerName) {
    if(!map){
      throw new Error("地图对象不能为空")
    }
    let srcLayer=map.getLayer(srcLayerName)
    if(!srcLayer){
      throw new Error(srcLayerName+"原图层不存在")
    }
    if(!map.getLayer(targetLayerName)){
      map.addLayer({
        id:targetLayerName,
        type:"fill",
        "source": srcLayer.source,
        "source-layer": srcLayer.sourceLayer||"",
        "minzoom": srcLayer.minzoom,
        "maxzoom": srcLayer.maxzoom,
        layout: {
          visibility:"visible"
        },
        paint: {
          "fill-opacity": 0,
        },
      });
      let filter= map.getFilter(srcLayerName);
      map.setFilter(targetLayerName,filter);
    }
  }
  /**
   * 图层
   * @param map 地图对象
   * @param srcLayerName 原图层名字
   * @param targetLayerName 高亮图层名字
   * @param filter 高亮条件
   * @param maxZoom 高亮最大缩放
   * @param minZoom 高亮最小缩放
   */
  static addXzqHeight(map,srcLayerName,targetLayerName,filter,maxZoom,minZoom) {
    if(!map){
      throw new Error("地图对象不能为空")
    }
    let srcLayer=map.getLayer(srcLayerName)
    if(!srcLayer){
      throw new Error(srcLayerName+"原图层不存在")
    }
    if(map.getLayer(targetLayerName)){
      throw new Error(targetLayerName+"图层已存在")
    }
    map.addLayer({
      id:targetLayerName,
      type:"line",
      "source": srcLayer.source,
      "source-layer": srcLayer.sourceLayer,
      "minzoom": minZoom||srcLayer.minzoom||1,
      "maxzoom": maxZoom||srcLayer.maxzoom||18,
      layout: {},
      paint: {
        "line-color": "#F9CB11",
        "line-width": 4,
      },
    })
    if(filter){
      map.setFilter(targetLayerName,filter);
    }

  }

  /**
   * 移除图层
   * @param map 地图对象
   * @param layerId 图层id
   */
  static removeLayer(map,layerId){
    if(map.getLayer(layerId)){
      map.removeLayer(layerId);
    }else {
      console.warn(layerId+"图层不存在")
    }
  }

  /**
   * 缩放到这个图层的可见范围
   * @param layerId 图层id
   * @param map 地图对象
   */
  static zoomToLayer(map,layerId){
    let srcLayer=map.getLayer(layerId)
    if(!srcLayer){
      throw new Error(layerId+"原图层不存在")
    }
    map.zoomTo(srcLayer.minzoom+0.1)
  }

  /**
   * 图层加载完成回调
   * @param layerId 图层id
   * @param map 地图对象
   */
  static nextLevelLoaded(map,layerId){
    return new Promise((resolve, reject) => {
      if(!layerId || !map.getSource(layerId)){
        resolve()
      }else{
        let interval = setInterval(() => {
          /*下一级别图层加载完认为地图停止,可以执行查询操作*/
          if (map.isSourceLoaded(layerId)) {
            clearInterval(interval);
            resolve();
          };
        }, 100);
      }
    });
  }

  /**
   *将feature合并为一个feature
   * featureArr feature 数组
   */
  static unionFeatures(featureArr){
    if(!featureArr || featureArr.length == 0){return "至少传入一个feature"}
    if(featureArr.length == 1){return featureArr[0]}
    let unioinedPolygon = "";/*合并后的结果*/
    featureArr.forEach((item,index) => {item.mergeId = index});/*添加ID表示唯一*/
    let copyFeatureArr = JSON.parse(JSON.stringify(featureArr));/*副本*/

    /*默认第一个已经合并*/
    let merged_id = [featureArr[0].mergeId];/*已经合并过的polygon ID*/
    unioinedPolygon = featureArr[0]
    for(let j = 0; j < featureArr.length ; j++){
      for(let i = 0;i < copyFeatureArr.length ; i++){
        /*合并过的不合并*/
        if(!merged_id.includes(copyFeatureArr[i].mergeId)){
          let temp_merge_res = MapCommon.merge_polygon_tow(unioinedPolygon,copyFeatureArr[i]);
          if(!temp_merge_res.msg){
            /*记录合并过的mergeId*/
            merged_id.push(copyFeatureArr[i].mergeId);
            unioinedPolygon = temp_merge_res.polygon;
          }
        }
      }
    }
    unioinedPolygon.properties = featureArr[0].properties;
    return unioinedPolygon
  }

  /**
   * 合并(只能合并两个polygon)
   * @params polygonA
   * @params polygonB
   * */
  static merge_polygon_tow(polygonA,polygonB){
    let msg = "";
    let unioinedPolygon = "";
    if(!polygonA || !polygonB){return {polygon:unioinedPolygon,msg:"请传入两个polygon Feature" }}

    let intersectPolygon = turf.intersect(polygonA,polygonB);
    if(intersectPolygon){
      unioinedPolygon = turf.union(polygonA,polygonB);
    }else{
      msg = `两个地块未接触不能合并`
    }
    return {polygon:unioinedPolygon,msg:msg }
  }
  /**
   * 合并(只能合并两个polygon)
   * @params polygonA
   * @params polygonB
   * @params buffer
   * */
  static merge_polygon_tow_buffer(polygonA,polygonB,buffer=10){
    let msg = "";
    let unioinedPolygon = "";
    if(!polygonA || !polygonB){return {polygon:unioinedPolygon,msg:"请传入两个polygon Feature" }}

    /*两个polygon分别增加一般的buffer*/
    let bufferedPolygonA = turf.buffer(polygonA,(0.001 * buffer)/2,'kilometers');
    let bufferedPolygonB = turf.buffer(polygonB,(0.001 * buffer)/2, 'kilometers');
    let intersectPolygon = turf.intersect(bufferedPolygonA,bufferedPolygonB);
    if(intersectPolygon){
      /*合并bugger之后的polygon*/
      let buffer_polygon_unioin = turf.union(bufferedPolygonA,bufferedPolygonB);
      /*将合并之后的polygon再去掉buffer*/
      unioinedPolygon =turf.buffer(buffer_polygon_unioin,-(0.001 * buffer)/2,'kilometers')
    }else{
      msg = `两个地块缓冲超过${buffer}米,不能合并`
    }
    return {polygon:unioinedPolygon,msg:msg }
  }

  /**
   *合并，合并多个polygon
   * @params polygonArr  polygon数组
   * @params buffer 缓冲距离，单位米
   */
  static unionPolygons(polygonArr = [],buffer = 2){

    let msg = "";/*错误提示信息*/
    let unioinedPolygon = "";/*合并后的结果*/
    if(polygonArr.length < 2){return {polygon:unioinedPolygon,msg:"请传入两个polygon Feature" }}
    let properties=JSON.parse(JSON.stringify(polygonArr[0].properties))
    polygonArr.forEach((item,index) => {item.mergeId = index});/*添加ID表示唯一*/
    let copyPolygonArr = JSON.parse(JSON.stringify(polygonArr));/*副本*/

    /*默认第一个已经合并*/
    let merged_id = [polygonArr[0].mergeId];/*已经合并过的polygon ID*/
    unioinedPolygon = polygonArr[0]
    for(let j = 0; j < polygonArr.length ; j++){
      for(let i = 0;i < copyPolygonArr.length ; i++){
        /*合并过的不合并*/
        if(!merged_id.includes(copyPolygonArr[i].mergeId)){
          let temp_merge_res = MapCommon.merge_polygon_tow_buffer(unioinedPolygon,copyPolygonArr[i],buffer);
          if(!temp_merge_res.msg){
            /*记录合并过的mergeId*/
            merged_id.push(copyPolygonArr[i].mergeId);
            unioinedPolygon = temp_merge_res.polygon;
          }else {
            msg=temp_merge_res.msg;
            break;
          }
        }
      }
    }

    /*不相等说明还有没合并进去的，即存在不符合条件的地块*/
    if(merged_id.length != polygonArr.length){
      unioinedPolygon = "";
      msg = `有地块缓冲超过${buffer}米,不能合并`;
    }
    unioinedPolygon.properties=properties;
    return {polygon:unioinedPolygon,msg:msg }
  }

  /**
   * 通过线分割多边形
   * @param polygon
   * @param line
   * @returns {{msg: string, features: []}}
   */
  static splitPolygon(polygon,line){
    let msg = "";/*信息*/
    let featuresR = [];/*分割后的单个polygon的feature*/
    console.log(turf);
    let sliceRes =  turf_line_intersect(polygon,line);/*计算分割点*/
    if(sliceRes){
      /*分割点小于2给提示*/
      if(sliceRes.features.length > 1){

        let bufferedLine = turf.buffer(line,0.0001)/*改为10cm防止multipolygon切割不到*/
        let difFeature = turf.difference(polygon,bufferedLine);
        /*遍历结果，处理将multipolygon解析为polygon*/
        // that.add_mask_layer_arr([dkFeature,difFeature])
        difFeature.geometry.coordinates.forEach(item => {
          MapCommon.handleMultiPolygon(item,featuresR,difFeature.properties);
        });
      }else{
        msg = "分割线与选中的地块至少两个相交点"
      }
    }else{
      msg = "分割线与选中的地块无相交点"
    }
    /*最终结果，这里还要计算一下，防止有空心多边形，这里每个feature与原地块feature做intersect，intersect为
需要的部分，并且要做buffer,否则计算不准或者卡死各种问题 */
    let final = [];/*与原地块intersect，要相交的部分*/
    featuresR.forEach(item => {
      let temp_buffer = turf.buffer(item,-0.0001);/*加buffer，缩小*/
      let tempFeature =  turf.intersect(polygon,temp_buffer);
      if(tempFeature){
        let tempFeature_buffered =  turf.buffer(tempFeature,0.0001);/*加buffer放大回来*/
        tempFeature_buffered.properties=JSON.parse(JSON.stringify(polygon.properties));
        final.push(tempFeature_buffered)
      }
    });
    return {features:final,msg:msg};
  }

  /**
   * 将multiPolygon的coordinates解析成polygonFeature
   * @param coordinates 要解析的coordinate
   * @param featuresR 存储解析的结果
   * @param properties 生成feature的属性
   */
  static handleMultiPolygon(coordinates,featuresR,properties){
    let hasMore = false;/*是否有大于2个的分割快*/
    for(let i = 0 ;i < coordinates.length ;i++){
      if(coordinates[i].length > 2){hasMore = true;break}
    }
    if(hasMore){
      coordinates.forEach(item => {
        MapCommon.handleMultiPolygon(item,featuresR,properties)
      })
    }else{
      featuresR.push(turf.feature({"type":"Polygon","coordinates":JSON.parse(JSON.stringify([coordinates]))},JSON.parse(JSON.stringify(properties))))
    }
  }

}




